import 'package:ddwidget/mixin/dd_controller_mixin.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter/material.dart';
import 'dart:io';

/// 异步渲染页面的初始化状态，
enum DDPageInitType {
  onlyLoadding, // 只显示Loadding
  onlystruture, // 不展示loadding
  strutureLoadding, // 既显示结构，其上加上Loadding
  bonesScreen, // 骨骼屏
}

//  Scaffold->PrimaryScrollController -> Material -> AnimatedPhysicalModel ->PhysicalModel -> NotificationListener<LayoutChangedNotification> -> AnimatedDefaultTextStyle->DefaultTextStyle->AnimatedBuilder->CustomMutiChildLayout
// -> MediaQuery
/// 自定义`脚手架`，用于合理的UI逻辑。
class DDScaffod extends StatefulWidget {
  final Widget? navigator;
  final Color backgroundColor;
  final Widget? body;

  /// 在body上层navigator下层的一些东西，布局基于stack,
  final List<Widget>? upbodys;
  final List<Widget>? downBodys;
  final Future? future;
  final Widget? bonesScreenWidget; // 骨架屏skeleton，的解决方案.
  final DDPageInitType initType;
  final DDScaffodController? controller;
  final bool tapAnyWhereHideKeyboard; // 点击任意区域隐藏键盘
  final bool canGestureBack; // 是否可以侧滑返回
  /// 在navigator上层的一些东西
  final List<Widget> popupWidget;

  const DDScaffod({
    Key? key,
    this.navigator,
    this.backgroundColor = const Color(0xffffffff),
    this.body,
    this.future,
    this.bonesScreenWidget,
    this.initType = DDPageInitType.onlyLoadding,
    this.controller,
    this.tapAnyWhereHideKeyboard = false,
    this.popupWidget = const [],
    this.canGestureBack = true,
    this.upbodys,
    this.downBodys,
  }) : super(key: key);

  @override
  DDScaffodState createState() => DDScaffodState();

  /// 获取当前脚手架的state[后面可以使用controller 控制脚手架的一些行为,例如展示loadding,隐藏loadding]
  static DDScaffodState? of(BuildContext context) {
    if (context is StatefulElement && context.state is DDScaffodState) {
      return context.state as DDScaffodState;
    }
    DDScaffodState? state = context.findAncestorStateOfType<DDScaffodState>();
    return state;
  }
}

class DDScaffodState extends State<DDScaffod> {
  Widget? _loaddingWidget;
  DDScaffodController? controller;
  // 插入树的时候调用
  @override
  void initState() {
    super.initState();
    _addControllerListener();
  }

  // 从树中永久移除时调用
  @override
  void dispose() {
    controller?.dispose();
    super.dispose();
  }

  // 添加控制器
  void _addControllerListener() {
    controller = widget.controller ?? DDScaffodController();
    controller?.addListener("showLoadding", (pars) {
      showLoading(
          block: pars["block"],
          child: pars["child"],
          milliseconds: pars["milliseconds"]);
    });
    controller?.addListener("hideLoadding", (pars) {
      hideLoading();
    });
  }

  /// 通过脚手架来展示loading
  void showLoading({bool block = true, Widget? child, int? milliseconds}) {
    controller?._isLoadding = true;
    _loaddingWidget = child;
    setState(() {});
    if (milliseconds != null) {
      Future.delayed(Duration(milliseconds: milliseconds)).then((value) {
        // ignore: unnecessary_null_comparison
        if (this != null) {
          hideLoading();
        }
      });
    }
  }

  /// 通过脚手架来hideloading
  void hideLoading() {
    controller?._isLoadding = false;
    _loaddingWidget = null;
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Material(
      color: widget.backgroundColor,
      child: widget.canGestureBack
          ? _body()
          : WillPopScope(
              child: _body(),
              onWillPop: () async {
                return false;
              },
            ),
    );
  }

  Widget _body() {
    final content = (widget.future == null)
        ? _DDScafodContent(
            body: widget.body,
            navigator: widget.navigator,
            popup: widget.popupWidget,
            upbody: widget.upbodys ?? const [],
            downBody: widget.downBodys ?? const [],
            loadding: controller?.isLoadding == true
                ? _DDScafodLoadding(
                    block: controller?._isLoaddingBlock,
                    loaddingWidget: _loaddingWidget,
                  )
                : null,
          )
        : FutureBuilder(
            builder: _futureAction,
            future: widget.future,
          );

    return widget.tapAnyWhereHideKeyboard
        ? GestureDetector(
            behavior: HitTestBehavior.opaque,
            onTap: () {
              /// 点击其他区域隐藏键盘
              FocusScopeNode currentFocus = FocusScope.of(context);
              if (!currentFocus.hasPrimaryFocus &&
                  currentFocus.focusedChild != null) {
                FocusManager.instance.primaryFocus?.unfocus();
              }
            },
            child: content,
          )
        : content;
  }

  Widget _futureAction(BuildContext context, AsyncSnapshot snapshot) {
    switch (snapshot.connectionState) {
      case ConnectionState.none:
      case ConnectionState.active:
      case ConnectionState.waiting:
        return _initLoaddingWidget(context)!;
      case ConnectionState.done:
        break;
    }
    return _DDScafodContent(
      body: widget.body,
      navigator: widget.navigator,
      popup: widget.popupWidget,
      downBody: widget.downBodys ?? const [],
      upbody: widget.upbodys ?? const [],
      loadding: controller?.isLoadding == true
          ? _DDScafodLoadding(
              block: controller?._isLoaddingBlock,
              loaddingWidget: _loaddingWidget,
            )
          : null,
    );
  }

  Widget? _initLoaddingWidget(BuildContext context) {
    bool showLoadding = false;
    bool showStrucure = true;
    bool showbouns = false;
    switch (widget.initType) {
      case DDPageInitType.onlyLoadding:
        showLoadding = true;
        showStrucure = false;
        break;
      case DDPageInitType.onlystruture:
        showLoadding = false;
        showStrucure = true;
        break;
      case DDPageInitType.strutureLoadding: // 如果指定这个,则需要保持树形结构统一
        showLoadding = true;
        showStrucure = true;
        break;
      case DDPageInitType.bonesScreen:
        showLoadding = false;
        showStrucure = false;
        showbouns = true;
        break;
      default:
    }
    return _DDScafodContent(
      body: showStrucure
          ? (showbouns ? widget.bonesScreenWidget : widget.body)
          : null,
      navigator: widget.navigator,
      popup: widget.popupWidget,
      upbody: widget.upbodys ?? const [],
      downBody: widget.downBodys ?? const [],
      loadding: showLoadding
          ? _DDScafodLoadding(
              block: controller?._isLoaddingBlock,
              loaddingWidget: _loaddingWidget,
            )
          : null,
    );
  }
}

/// 抽象content组件
class _DDScafodContent extends StatelessWidget {
  final Widget? navigator;
  final Widget? body;
  final List<Widget> upbody;
  final List<Widget> popup;
  final List<Widget> downBody;
  final _DDScafodLoadding? loadding;
  const _DDScafodContent(
      {Key? key,
      this.navigator,
      this.popup = const [],
      this.body,
      this.upbody = const [],
      this.loadding,
      this.downBody = const []})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    final newBody = Padding(
      padding: navigator != null
          ? EdgeInsets.only(top: 44 + MediaQuery.of(context).padding.top)
          : EdgeInsets.zero,
      child: body,
    );
    return Stack(
      children: [
        for (var i in downBody) i,
        newBody,
        for (var i in upbody) i,
        if (navigator != null) navigator!,
        for (var i in popup) i,
        if (loadding != null) loadding!,
      ],
    );
  }
}

/// 抽象loadding小组件，提升setState效率
class _DDScafodLoadding extends StatelessWidget {
  final bool? block;
  final Widget? loaddingWidget;
  const _DDScafodLoadding({Key? key, this.block = true, this.loaddingWidget})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      color: (block == true) ? const Color(0x00000000) : null,
      child: Center(
        child: loaddingWidget ??
            ((Platform.isIOS || Platform.isMacOS)
                ? const CupertinoActivityIndicator()
                : const CircularProgressIndicator()),
      ),
    );
  }
}

/// 脚手架控制器
class DDScaffodController with DDControllerMixin {
  bool _isLoadding = false;

  /// 获取是否处于loadding 的状态[导航栏的交互需要loadding 的话需要用此状态来控制]
  bool get isLoadding => _isLoadding;

  /// 用于脚手架内部管理
  bool _isLoaddingBlock = true;
  // 展示loadding 动画
  showLoading({bool block = true, Widget? child, int? milliseconds}) {
    if (isLoadding) {
      return;
    }
    _isLoadding = true;
    _isLoaddingBlock = block;
    dispatch("showLoadding", {
      "block": block,
      "child": child,
      "milliseconds": milliseconds,
    });
  }

  void hideLoading() {
    _isLoadding = false;
    dispatch("hideLoadding", null);
  }
}

/// state mixin this can use scaffodController
mixin DDStateWithScaffodCtrlMixin<T extends StatefulWidget> on State<T> {
  late DDScaffodController scaffodController;
  @override
  void initState() {
    super.initState();
    scaffodController = DDScaffodController();
  }

  @override
  void dispose() {
    scaffodController.dispose();
    super.dispose();
  }
}
